package br.gov.ms.tce.modelo.config;

import java.io.File;
import java.io.FileNotFoundException;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;

public class DataSourceFactory {

	private final Log log = LogFactory.getLog(DataSourceFactory.class);

	private String jndiDatasourceName;

	private String driverClassName;
	private String url;
	private String username;
	private String password;
	private Integer maxActive;
	private Integer maxIdle;
	private Integer maxWait;
	private Boolean poolPreparedStatements;
	private Integer maxOpenPreparedStatements;

	private DataSource currentDataSource = null;

	private HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();

	public void setJndiDatasourceName(String jndiDatasourceName) {
		this.jndiDatasourceName = jndiDatasourceName;
	}

	public void init() {
		log.warn("Initializing database connection pool.");
		try {
			Context initContext = new InitialContext();
			Context envContext = (Context) initContext.lookup("java:/comp/env");
			DataSource jndiDataSource = (DataSource) envContext
					.lookup(this.jndiDatasourceName);

			Connection conn = jndiDataSource.getConnection();
			conn.close();
			this.currentDataSource = jndiDataSource;
			this.hibernateJpaVendorAdapter.setDatabase(Database.POSTGRESQL);
			log.warn("Banco de Dados JNDI Encontrado com Sucesso.");
		} catch (Exception e) {
			log.warn("Banco de Dados JNDI Não Encontrado.");
			launchHsqldbDataSource();
		}
	}

	/**
	 * Launch an in-memory HSQLDB database, and create a datasource from it.
	 */
	private void launchHsqldbDataSource() {
		this.hibernateJpaVendorAdapter.setDatabase(Database.HSQL);
		this.hibernateJpaVendorAdapter.setGenerateDdl(true);
		this.hibernateJpaVendorAdapter.setShowSql(true);
		try {
			BasicDataSource hsqldbDataSource = new BasicDataSource();
			hsqldbDataSource.setDriverClassName(driverClassName);
			hsqldbDataSource.setUrl(url);
			hsqldbDataSource.setUsername(username);
			hsqldbDataSource.setPassword(password);
			hsqldbDataSource.setMaxActive(maxActive);
			hsqldbDataSource.setMaxIdle(maxIdle);
			hsqldbDataSource.setMaxWait(maxWait);
			hsqldbDataSource.setPoolPreparedStatements(poolPreparedStatements);
			hsqldbDataSource.setMaxOpenPreparedStatements(maxOpenPreparedStatements);
			
			Connection conn = hsqldbDataSource.getConnection();
			Statement stmt = conn.createStatement();
			stmt.execute("CREATE SCHEMA COMUM AUTHORIZATION DBA");
						
			stmt.close();
			//executeSqlScript(conn, new File(DataSourceFactory.class.getResource("/userdb.script").getFile()));
			conn.close();
			
			this.currentDataSource = hsqldbDataSource;
			log.warn("Inciado o banco HSQLDB.");
		} catch (SQLException sqle) {
			log.warn("O banco HSQLDB Não Foi Iniciado: "
					+ sqle.getMessage());

			sqle.printStackTrace();
			log.fatal("Nenhum banco foi inicializado!");
		}
	}
	
	public void executeSqlScript(Connection conn, File inputFile) {

	    // Delimiter
	    String delimiter = "\n";

	    // Create scanner
	    Scanner scanner;
	    try {
	        scanner = new Scanner(inputFile).useDelimiter(delimiter);
	    } catch (FileNotFoundException e1) {
	        e1.printStackTrace();
	        return;
	    }

	    // Loop through the SQL file statements 
	    Statement currentStatement = null;
	    while(scanner.hasNext()) {

	        // Get statement 
	        String rawStatement = scanner.next() + delimiter;
	        try {
	            // Execute statement
	            currentStatement = conn.createStatement();
	            currentStatement.execute(rawStatement);
	        } catch (SQLException e) {
	            e.printStackTrace();
	        } finally {
	            // Release resources
	            if (currentStatement != null) {
	                try {
	                    currentStatement.close();
	                } catch (SQLException e) {
	                    e.printStackTrace();
	                }
	            }
	            currentStatement = null;
	        }
	    }
	}

	public DataSource getDataSource() {
		return this.currentDataSource;
	}

	public HibernateJpaVendorAdapter getHibernateJpaVendorAdapter() {
		return this.hibernateJpaVendorAdapter;
	}

	public void setDriverClassName(String driverClassName) {
		this.driverClassName = driverClassName;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public void setMaxActive(Integer maxActive) {
		this.maxActive = maxActive;
	}

	public void setMaxIdle(Integer maxIdle) {
		this.maxIdle = maxIdle;
	}

	public void setMaxWait(Integer maxWait) {
		this.maxWait = maxWait;
	}

	public void setPoolPreparedStatements(Boolean poolPreparedStatements) {
		this.poolPreparedStatements = poolPreparedStatements;
	}

	public void setMaxOpenPreparedStatements(Integer maxOpenPreparedStatements) {
		this.maxOpenPreparedStatements = maxOpenPreparedStatements;
	}
	

}
